package example.wikipedia;

import com.google.gson.TypeAdapter;
import com.google.gson.stream.JsonReader;
import com.google.gson.stream.JsonWriter;

import java.io.IOException;

abstract class ResponseAdapter<X> extends TypeAdapter<WikipediaExample.Response<X>> {

    /**
     * name of the key inside the {@code query} dict which holds the elements desired. ex. {@code
     * pages}.
     */
    protected abstract String query();

    /**
     * Parses the contents of a result object.
     *
     * <p><br>
     * ex. If {@link #query()} is {@code pages}, then this would parse the value of each key in the
     * dict {@code pages}. In the example below, this would first start at line {@code 3}.
     *
     * <p>
     *
     * <pre>
     * "pages": {
     *   "2576129": {
     *     "pageid": 2576129,
     *     "title": "Burchell's zebra",
     * --snip--
     * </pre>
     */
    protected abstract X build(JsonReader reader) throws IOException;

    /**
     * the wikipedia api doesn't use json arrays, rather a series of nested objects.
     */
    @Override
    public WikipediaExample.Response<X> read(JsonReader reader) throws IOException {
        WikipediaExample.Response<X> pages = new WikipediaExample.Response<X>();
        reader.beginObject();
        while (reader.hasNext()) {
            String nextName = reader.nextName();
            if ("query".equals(nextName)) {
                reader.beginObject();
                while (reader.hasNext()) {
                    if (query().equals(reader.nextName())) {
                        reader.beginObject();
                        while (reader.hasNext()) {
                            // each element is in form: "id" : { object }
                            // this advances the pointer to the value and skips the key
                            reader.nextName();
                            reader.beginObject();
                            pages.add(build(reader));
                            reader.endObject();
                        }
                        reader.endObject();
                    } else {
                        reader.skipValue();
                    }
                }
                reader.endObject();
            } else
                if ("continue".equals(nextName)) {
                    reader.beginObject();
                    while (reader.hasNext()) {
                        if ("gsroffset".equals(reader.nextName())) {
                            pages.nextOffset = reader.nextLong();
                        } else {
                            reader.skipValue();
                        }
                    }
                    reader.endObject();
                } else {
                    reader.skipValue();
                }
        }
        reader.endObject();
        return pages;
    }

    @Override
    public void write(JsonWriter out, WikipediaExample.Response<X> response) throws IOException {
        throw new UnsupportedOperationException();
    }
}
